Adding some more judges, here and there.
[and.git] / ICPC Live Archive / 3928 - Ballroom lights / help / gomox.ar-pap-2010-d9b17e5cb110 / tpc / new-distinct-substrings / main.cpp
blob32f34b852e5a19e22c4dc9390eb73971d184e6e5
1 #include <string.h>
2 #include <cstdio>
3 #include <algorithm>
5 using std::sort;
6 using std::swap;
8 static char text[50001];
9 static unsigned int sa[50000];
10 static unsigned int rank1[50000]={0};
11 static unsigned int rank2[50000]={0};
13 static int N;
14 static long long total;
15 static unsigned cuantos;
17 bool parar;
18 int bucket, aux, desde, actual;
19 unsigned int* ahora;
20 unsigned int* proximo;
23 // Comparador
24 struct Comparador {
25 const int K;
26 const unsigned int* rank;
27 Comparador(const int j,const unsigned int* vrank): K(j), rank(vrank) {};
29 bool inline operator()(const int i, const int j) const {
30 return clave(i) < clave(j);
33 int inline clave(const int i) const {
34 return (i+K < N ? rank[i+K]+1 : 0);
39 int main(int argc, const char *argv[]) {
41 scanf("%d", &cuantos);
43 for (int c = 0; c < cuantos; c++) {
45 scanf("%s", text);
46 N = strlen(text);
48 // Suffix Array
49 for (int i = 0; i < N; i++) {
50 sa[i] = i;
51 rank1[i] = text[i];
55 sort(sa, sa+N, Comparador(0, rank1));
57 bucket = 0;
58 rank1[sa[0]] = 0;
60 for (int t = 1; t < N; t++) {
61 if (text[sa[t-1]] == text[sa[t]]) {
62 rank1[sa[t]] = bucket;
63 } else {
64 bucket = t;
65 rank1[sa[t]] = bucket;
69 parar = true;
70 ahora = rank1;
71 proximo = rank2;
73 for (int K = 1; K < N; K *= 2) {
74 desde = 0;
75 actual = 1;
76 Comparador comparador(K,ahora);
77 while (actual < N) {
78 while (actual< N && ahora[sa[actual]] == ahora[sa[actual-1]]) {
79 actual++;
81 if (actual > desde+1) {
82 sort(sa+desde, sa+actual, comparador);
84 desde = actual;
85 actual++;
88 bucket = 0;
89 proximo[sa[0]] = 0;
90 aux = 0;
92 for (int t = 1; t < N; t++) {
93 if (ahora[sa[t]] == aux && comparador.clave(sa[t-1]) == comparador.clave(sa[t])) {
94 proximo[sa[t]] = bucket;
95 parar = false;
96 } else {
97 aux = ahora[sa[t]];
98 bucket = t;
99 proximo[sa[t]] = bucket;
103 swap(ahora, proximo);
104 if (parar) break;
105 parar = true;
108 // LCP (Kasai)
109 total = 0;
110 int k = 0;
111 for (int i = 0; i < N; i++) {
112 if (k > 0) {
113 k--;
115 if (ahora[i] == N-1) {
116 total += N + 1 - sa[N-1];
117 k = 0;
118 continue;
120 int j = sa[ahora[i]+1];
121 while (text[i+k] == text[j+k]) k++;
122 total += N - k - sa[ahora[i]];
125 // El codigo de arriba pone un -1 en la
126 // fila final del LCP en lugar de un 0 en la primera,
127 // asi que hay que restarlo ahora.
128 total = total - 1;
130 printf("%lld\n", total);